//
//  foc_problem.cpp
//  NLCEQ_mixed
//
//  Created by Duong Ngo on 8/15/16.
//  Copyright © 2016 Duong Ngo. All rights reserved.
//

#include "foc_problem.hpp"
#include "foc_nlp.hpp"
#include "IpIpoptApplication.hpp"

int foc_solve(const std::vector<double>& x_init, bool& success)
{
    // Create a new instance of your nlp
    //  (use a SmartPtr, not raw)
    SmartPtr<TNLP> mynlp = new foc_nlp(x_init);
    
    // Create a new instance of IpoptApplication
    //  (use a SmartPtr, not raw)
    // We are using the factory, since this allows us to compile this
    // example with an Ipopt Windows DLL
    SmartPtr<IpoptApplication> app = IpoptApplicationFactory();
    app->RethrowNonIpoptException(true);
    
    // Change some options
    // Note: The following choices are only examples, they might not be
    //       suitable for your optimization problem.
    app->Options()->SetNumericValue("tol", 1e-15);
    app->Options()->SetNumericValue("bound_push", 1e-50);
    app->Options()->SetNumericValue("bound_frac", 1e-50);
    app->Options()->SetNumericValue("constr_viol_tol", 1e-15);
    app->Options()->SetIntegerValue("print_level", 5);
    app->Options()->SetIntegerValue("max_iter", 500);
    app->Options()->SetStringValue("mu_strategy", "adaptive");
    app->Options()->SetStringValue("output_file", "ipopt.out");
    app->Options()->SetStringValue("linear_solver", "ma27");
    app->Options()->SetStringValue("hessian_approximation", "limited-memory");

    
    app->Options()->SetStringValue("derivative_test", "first-order");
    
    // The following overwrites the default name (ipopt.opt) of the
    // options file
    // app->Options()->SetStringValue("option_file_name", "hs071.opt");
    
    // Initialize the IpoptApplication and process the options
    ApplicationReturnStatus status;
    status = app->Initialize();
    if (status != Solve_Succeeded) {
        std::cout << std::endl << std::endl << "*** Error during initialization!" << std::endl;
        return (int) status;
    }
    
    // Ask Ipopt to solve the problem
    status = app->OptimizeTNLP(mynlp);
    
    if (status == Solve_Succeeded) {
        success=true;
        std::cout << std::endl << std::endl << "*** The problem solved!" << std::endl;
    }
    else {
        success=false;
        std::cout << std::endl << std::endl << "*** The problem FAILED!" << std::endl;
    }
    
    // As the SmartPtrs go out of scope, the reference count
    // will be decremented and the objects will automatically
    // be deleted.
    
    
    return (int) status;

}